home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
ada
/
gnat1792.zip
/
gnat179b
/
t-adainc
/
s-taprob.adb
< prev
next >
Wrap
Text File
|
1994-05-19
|
21KB
|
657 lines
------------------------------------------------------------------------------
-- --
-- GNU ADA RUNTIME LIBRARY (GNARL) COMPONENTS --
-- --
-- S Y S T E M . T A S K I N G . P R O T E C T E D _ O B J E C T S --
-- --
-- B o d y --
-- --
-- $Revision: 1.9 $ --
-- --
-- Copyright (c) 1991,1992,1993, FSU, All Rights Reserved --
-- --
-- GNARL is free software; you can redistribute it and/or modify it under --
-- terms of the GNU Library General Public License as published by the --
-- Free Software Foundation; either version 2, or (at your option) any --
-- later version. GNARL is distributed in the hope that it will be use- --
-- ful, but but WITHOUT ANY WARRANTY; without even the implied warranty of --
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Gen- --
-- eral Library Public License for more details. You should have received --
-- a copy of the GNU Library General Public License along with GNARL; see --
-- file COPYING. If not, write to the Free Software Foundation, 675 Mass --
-- Ave, Cambridge, MA 02139, USA. --
-- --
------------------------------------------------------------------------------
with System.Compiler_Exceptions;
-- Used for, Compiler_Exceptions."="
-- Compiler_Exceptions.Raise_Exceptions
with System.Error_Reporting;
-- Used for, System.Error_Reporting.Assert
with System.Tasking.Abortion;
-- Used for, Abortion.Defer_Abortion,
-- Abortion.Undefer_Abortion
-- Abortion.Abort_To_Level
with System.Task_Primitives; use System.Task_Primitives;
with System.Tasking.Runtime_Types;
-- Used for, Runtime_Types.ATCB_Ptr,
-- Runtime_Types.ATCB_To_ID,
-- Runtime_Types.ID_To_ATCB
package body System.Tasking.Protected_Objects is
procedure Assert (B : Boolean; M : String)
renames Error_Reporting.Assert;
function ID_To_ATCB (ID : Task_ID) return Runtime_Types.ATCB_Ptr
renames Tasking.Runtime_Types.ID_To_ATCB;
function ATCB_To_ID (Ptr : Runtime_Types.ATCB_Ptr) return Task_ID
renames Runtime_Types.ATCB_To_ID;
procedure Defer_Abortion
renames Abortion.Defer_Abortion;
procedure Undefer_Abortion
renames Abortion.Undefer_Abortion;
-- function "=" (L, R : System.Address) return Boolean renames System."=";
-- why is this commented out ???
function "=" (L, R : Runtime_Types.ATCB_Ptr) return Boolean
renames Runtime_Types."=";
-- This is temporarily commented out. Gnat produces internal error ???
-- function "=" (L, R : Task_ID) return Boolean
-- renames "=";
function "=" (L, R : Exception_ID) return Boolean
renames Compiler_Exceptions."=";
-----------------------------
-- Raise_Pending_Exception --
-----------------------------
procedure Raise_Pending_Exception (Block : Communication_Block) is
T : Runtime_Types.ATCB_Ptr := ID_To_ATCB (Block.Self);
Ex : Exception_ID := T.Exception_To_Raise;
begin
T.Exception_To_Raise := Null_Exception;
Compiler_Exceptions.Raise_Exception (Ex);
end Raise_Pending_Exception;
---------------------
-- Check_Exception --
---------------------
procedure Check_Exception is
T : Runtime_Types.ATCB_Ptr := ID_To_ATCB (Self);
Ex : Exception_ID := T.Exception_To_Raise;
begin
T.Exception_To_Raise := Null_Exception;
Compiler_Exceptions.Raise_Exception (Ex);
end Check_Exception;
---------------------------
-- Initialize_Protection --
---------------------------
procedure Initialize_Protection
(Object : Protection_Access;
Ceiling_Priority : Integer)
is
Init_Priority : Integer := Ceiling_Priority;
begin
if Init_Priority = Unspecified_Priority then
Init_Priority := System.Default_Priority;
end if;
Initialize_Lock (Init_Priority, Object.L);
Object.Pending_Call := null;
Object.Call_In_Progress := null;
for E in Object.Entry_Queues'range loop
Object.Entry_Queues (E).Head := null;
Object.Entry_Queues (E).Tail := null;
end loop;
end Initialize_Protection;
-------------------------
-- Finalize_Protection --
-------------------------
procedure Finalize_Protection (Object : Protection_Access) is
begin
-- Need to purge entry queues and pending entry call here. ???
Finalize_Lock (Object.L);
end Finalize_Protection;
----------
-- Lock --
----------
procedure Lock (Object : Protection_Access) is
begin
Write_Lock (Object.L);
end Lock;
--------------------
-- Lock_Read_Only --
--------------------
procedure Lock_Read_Only (Object : Protection_Access) is
begin
Read_Lock (Object.L);
end Lock_Read_Only;
------------
-- Unlock --
------------
procedure Unlock (Object : Protection_Access) is
begin
Unlock (Object.L);
end Unlock;
--------------------------
-- Protected_Entry_Call --
--------------------------
procedure Protected_Entry_Call
(Object : Protection_Access;
E : Protected_Entry_Index;
Uninterpreted_Data : System.Address;
Mode : Call_Modes;
Block : out Communication_Block)
is
Level : ATC_Level;
Caller : Runtime_Types.ATCB_Ptr := ID_To_ATCB (Self);
begin
Block.Self := ATCB_To_ID (Caller);
Caller.ATC_Nesting_Level := Caller.ATC_Nesting_Level + 1;
Level := Caller.ATC_Nesting_Level;
Object.Pending_Call := Caller.Entry_Calls (Level)'access;
-- I don't think that we need the calling task's lock here.
-- Only the calling task will get to access this record until
-- it is queued, since the calling task
-- will call Next_Entry_Call before releasing the PO lock,
-- and since Next_Entry_Call always removes Pending_Call. ???
Object.Pending_Call.Next := null;
Object.Pending_Call.Call_Claimed := False;
Object.Pending_Call.Mode := Mode;
Object.Pending_Call.Abortable := True;
Object.Pending_Call.Done := False;
Object.Pending_Call.E := Entry_Index (E);
Object.Pending_Call.Prio := Caller.Current_Priority;
Object.Pending_Call.Uninterpreted_Data := Uninterpreted_Data;
Object.Pending_Call.Called_PO := Protection_Access (Object);
Object.Pending_Call.Called_Task := Null_Task;
Object.Pending_Call.Exception_To_Raise := Null_Exception;
end Protected_Entry_Call;
--------------------------------------------
-- Vulnerable_Cancel_Protected_Entry_Call --
--------------------------------------------
procedure Vulnerable_Cancel_Protected_Entry_Call
(Caller : Runtime_Types.ATCB_Ptr;
Call : Entry_Call_Link;
PO : Protection_Access;
Call_Cancelled : out Boolean)
is
TAS_Result : Boolean;
begin
Test_And_Set (Call.Call_Claimed'Address, TAS_Result);
if TAS_Result then
Lock (PO);
Dequeue (PO.Entry_Queues (Protected_Entry_Index (Call.E)), Call);
else
Write_Lock (Caller.L);
while not Call.Done loop
Cond_Wait (Caller.Rend_Cond, Caller.L);
end loop;
Unlock (Caller.L);
end if;
Caller.ATC_Nesting_Level := Caller.ATC_Nesting_Level - 1;
Write_Lock (Caller.L);
if Caller.Pending_ATC_Level = Caller.ATC_Nesting_Level then
Caller.Pending_ATC_Level := ATC_Level